home *** CD-ROM | disk | FTP | other *** search
/ Aminet 28 / Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso / Aminet / game / board / Exchess.lha / EXChess / book.cpp < prev    next >
C/C++ Source or Header  |  1998-08-17  |  15KB  |  545 lines

  1. /* Book.Cpp functions to construct a book file from
  2.    a pgn-like text */
  3.  
  4. #include "chess.h"
  5. #include "define.h"
  6. #include "funct.h"
  7. #include "const.h"
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <iostream.h>
  11. #include <fstream.h>
  12. #include <math.h>
  13. #include <time.h>
  14.  
  15. // define 64 bit integers
  16. #if !BORLAND
  17.  #define __int64 long long
  18.  #define ZERO 0ULL
  19. #else
  20.  #define ZERO 0ui64
  21. #endif
  22.  
  23. #if DEC
  24.  #define IOS_OUT ios::out
  25.  #define IOS_IN  ios::in
  26. #else
  27.  #define IOS_OUT ios::out | ios::binary
  28.  #define IOS_IN  ios::in | ios::binary
  29. #endif
  30.  
  31. // Maximum line depth in ply
  32. #define LINE_DEPTH 30
  33. // Theshold  of move score to use
  34. #define THRESH 3
  35. // Maximum number of book positions in a temp file
  36. #define BOOK_POS 20000
  37. // Maximum number of temp files
  38. #define TEMP_FILES 200
  39.  
  40. struct book_rec {
  41.  unsigned __int64 pos_code;
  42.  int mcount;
  43.  move_rec bmoves[10];
  44.  int dummy;                    // to make record a multile byte size of 96
  45. };
  46.  
  47. extern int T, shout_book;      // Turn variable, loud book variable
  48.  
  49. typedef book_rec TT;
  50. typedef book_rec TblIndex;
  51. #define CompGT(a,b) (a > b)
  52.  
  53. void QuickSort(TT *Lb, TT *Ub);
  54. void ISort(TT *Lb, TT *Ub);
  55.  
  56. float ran1(long *idum);           // random number generator
  57. int absl(int);
  58.  
  59. book_rec learn_book[100];         // book learning array
  60. int learn_count = 0;
  61. int learn_move[100];
  62. int learn_filepos[100];
  63.  
  64. int chunk_count;
  65. book_rec chunk_record[TEMP_FILES];
  66. fstream chunk_file[TEMP_FILES];
  67.  
  68. extern char exec_path[100];           // from argv[0]
  69.  
  70. void build_book(position ipos)
  71. {
  72.   book_rec *record, *record_place;
  73.  
  74.   chunk_count = 1;  int p, pp;
  75.  
  76.   record = new book_rec[BOOK_POS];
  77.  
  78.   // initialize record structure
  79.   for(p = 0; p < BOOK_POS; p++) {
  80.    record[p].pos_code = ZERO;
  81.    record[p].mcount = 0;
  82.    for(pp = 0; pp < 10; pp++) {
  83.     record[p].bmoves[pp].m.t = 0;
  84.     record[p].bmoves[pp].score = 0;
  85.    }
  86.   }
  87.  
  88.   char file[20], instring[100], line[100], chunk[10];
  89.   position temp_pos;
  90.   move bmove;
  91.   unsigned __int64 pcode;
  92.   int i = -1, j = 0, k = 0, count = 0;
  93.  
  94.   cout << " Enter name of book text file: ";
  95.   cin >> file;
  96.  
  97.   cout << " Building book.... please wait.\n";
  98.  
  99.   ifstream infile(file);
  100.  
  101.   if(!infile) { cout << "File not found!\n"; return; }
  102.  
  103.   infile.seekg(0,ios::end);
  104.   unsigned long file_size = infile.tellg();
  105.   infile.seekg(0,ios::beg);
  106.  
  107.   while(!infile.eof()) {
  108.     infile >> instring;
  109.     switch(instring[0]) {
  110.      case '[':
  111.       i++; count=0; infile.getline(line,99); temp_pos = ipos; break;
  112.      case '1': break;
  113.      case '2': break;
  114.      case '3': break;
  115.      case '4': break;
  116.      case '5': break;
  117.      case '6': break;
  118.      case '7': break;
  119.      case '8': break;
  120.      case '9': break;
  121.      default :
  122.        count++; if(count > LINE_DEPTH) break;
  123.        bmove = parse_move(temp_pos, instring);
  124.        if(!bmove.t) { count = LINE_DEPTH; break; }
  125.        pcode = ZERO;
  126.        pcode = pcode|temp_pos.hcode.key;
  127.        pcode = (pcode<<32)|(temp_pos.hcode.address);
  128.        record_place = record;
  129.  
  130.        for(j = 0; ; j++) {
  131.           if(record_place->pos_code == pcode ||
  132.               !record_place->pos_code) break;
  133.           record_place++;
  134.         }
  135.  
  136.        if(!(j%1000) && j) {
  137.          cout << "Adding " << j << "th record to chunk " 
  138.               << chunk_count << ", " << (infile.tellg()*100)/file_size << "% done\n";
  139.          cout.flush();
  140.        }
  141.        record_place->pos_code = pcode;
  142.        for(k = 0; k < 10; k++)
  143.         { if(record_place->bmoves[k].m.t == bmove.t
  144.              || !record_place->bmoves[k].m.t) break; }
  145.        if(k < 10) {
  146.         record_place->bmoves[k].m.t = bmove.t;
  147.         record_place->bmoves[k].score++;
  148.         for(k = 0; k < 10; k++)
  149.          { if(!record_place->bmoves[k].m.t) break; }
  150.         record_place->mcount = k;
  151.        }
  152.        exec_move(&temp_pos, bmove, 1);
  153.        break;
  154.     }
  155.  
  156.     if (j>=BOOK_POS-1) {
  157.       if(chunk_count >= TEMP_FILES) break;
  158.       cout << "Sorting records for chunk " << chunk_count << "\n";
  159.       for(j = 0; j < BOOK_POS-1; j++)
  160.        { record_place = record+j;
  161.          if(!record_place->pos_code) break; }
  162.       QuickSort(record, record_place-1);
  163.       sprintf(chunk, "temp_bk.%i", chunk_count);
  164.       chunk_file[chunk_count-1].open(chunk, IOS_IN | IOS_OUT);
  165.       for(i = 0; i < j; i++) {
  166.        record_place = record+i;
  167.        Sort(&record_place->bmoves[0],&record_place->bmoves[record_place->mcount-1]);
  168.        chunk_file[chunk_count-1].write((char *) record_place, sizeof(book_rec));
  169.       } 
  170.       chunk_count++;     
  171.         // initialize record structure
  172.       for(p = 0; p < BOOK_POS; p++) {
  173.        record[p].pos_code = ZERO;
  174.        record[p].mcount = 0;
  175.        for(pp = 0; pp < 10; pp++) {
  176.         record[p].bmoves[pp].m.t = 0;
  177.         record[p].bmoves[pp].score = 0;
  178.        }
  179.       }
  180.       j = 0; 
  181.     }
  182.   }
  183.  
  184.   for(j = 0; j < BOOK_POS-1; j++)
  185.    { record_place = record+j;
  186.      if(!record_place->pos_code) break; }
  187.  
  188.   cout << "Sorting records for last chunk\n ";
  189.   cout.flush();
  190.   QuickSort(record, record_place-1);
  191.  
  192.       sprintf(chunk, "temp_bk.%i", chunk_count);
  193.       chunk_file[chunk_count-1].open(chunk, IOS_IN | IOS_OUT);
  194.       for(i = 0; i < j; i++) {
  195.        record_place = record+i;
  196.        Sort(&record_place->bmoves[0],&record_place->bmoves[record_place->mcount-1]);
  197.        chunk_file[chunk_count-1].write((char *) record_place, sizeof(book_rec));
  198.       } 
  199.  
  200.   ofstream out("open_bk.dat", IOS_OUT);
  201.   cout << "Writing book file...\n";
  202.   int min;
  203.  
  204.    min = 0;
  205.  
  206.    // first reading in a record from each chunk
  207.    for(i = 0; i < chunk_count; i++) {
  208.       if(chunk_file[i].eof()) { chunk_file[i].close(); break; }
  209.       chunk_file[i].seekg(0,ios::beg);
  210.       chunk_file[i].read((char *) &chunk_record[i], sizeof(book_rec));
  211.    }
  212.  
  213.  while(1) {
  214.  
  215.    // Now probe for minimum entry
  216.    min = 0;
  217.    for(i = 0; i < chunk_count; i++) {
  218.      if(min == i && !chunk_record[i].pos_code) { min++; continue; }
  219.      if(chunk_record[min].pos_code > chunk_record[i].pos_code &&
  220.         chunk_record[i].pos_code) min = i;
  221.    }  
  222.  
  223.    if(min == chunk_count) break;     
  224.        
  225.    // merge all minimum records together - reading in more when necessary
  226.    for(i = 0; i < chunk_count; i++) {
  227.      if(i == min) continue;
  228.      if(chunk_record[min].pos_code == chunk_record[i].pos_code) {
  229.          // merging records
  230.          for(j = 0; j < chunk_record[min].mcount; j++) {
  231.           for(k = 0; k < chunk_record[i].mcount; k++) {
  232.             if(chunk_record[min].bmoves[j].m.t == chunk_record[i].bmoves[k].m.t) {
  233.              chunk_record[min].bmoves[j].score += chunk_record[i].bmoves[k].score;
  234.              chunk_record[i].bmoves[k].score = -1;  // flag it as merged
  235.              break;
  236.             }
  237.           }               
  238.          }
  239.          for(k = 0 ; k < chunk_record[i].mcount; k++) { 
  240.             if(chunk_record[i].bmoves[k].score > 0 && j < 10) {
  241.                chunk_record[min].bmoves[j].m.t = chunk_record[i].bmoves[k].m.t;
  242.                chunk_record[min].bmoves[j].score = chunk_record[i].bmoves[k].score;
  243.                j++;
  244.             }
  245.          } 
  246.          chunk_record[min].mcount = j;
  247.          Sort(&chunk_record[min].bmoves[0],&chunk_record[min].bmoves[j-1]);
  248.          if(!chunk_file[i].eof())
  249.           chunk_file[i].read((char *) &chunk_record[i], sizeof(book_rec));
  250.          else chunk_record[i].pos_code = ZERO;
  251.      }
  252.    }
  253.    
  254.    if (chunk_record[min].bmoves[0].score >= THRESH)
  255.     out.write((char *) &chunk_record[min], sizeof(book_rec));
  256.  
  257.    if(!chunk_file[min].eof())
  258.        chunk_file[min].read((char *) &chunk_record[min], sizeof(book_rec));
  259.    else chunk_record[min].pos_code = ZERO;
  260.    
  261.   
  262.   }
  263.   
  264.   // remove temporary files
  265.   for(j = 1; j <= chunk_count; j++) {
  266.      chunk_file[j-1].close();
  267.      sprintf(chunk, "temp_bk.%i", j);
  268.      if(remove(chunk) == -1) cout << "Error deleting " << chunk << "\n";
  269.   }
  270.  
  271.   out.close();
  272.   delete [] record;
  273. }
  274.  
  275. move opening_book(h_code hash_code, position *p)
  276. {
  277.   unsigned __int64 pcode = ZERO;
  278.   book_rec